package com.ticket.sass.provider.business.impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ticket.sass.common.entity.tenant.AdminEntity;
import com.ticket.sass.common.entity.tenant.CinemaEntity;
import com.ticket.sass.common.exception.enums.ErrorCode;
import com.ticket.sass.common.exception.exception.BadRequestException;
import com.ticket.sass.provider.business.AdminBusiness;
import com.ticket.sass.provider.config.AppConfig;
import com.ticket.sass.provider.dto.admin.AdminInfoOutput;
import com.ticket.sass.provider.dto.admin.AdminListOutput;
import com.ticket.sass.provider.dto.input.admin.AdminAddInput;
import com.ticket.sass.provider.dto.input.admin.AdminListInput;
import com.ticket.sass.provider.dto.input.admin.AdminLoginInput;
import com.ticket.sass.provider.dto.input.admin.AdminUpdInput;
import com.ticket.sass.provider.service.PageModel;
import com.ticket.sass.provider.service.impl.AdminServiceImpl;
import com.ticket.sass.provider.service.impl.CinemaServiceImpl;
import com.ticket.sass.provider.service.impl.TenantCinemaMapServiceImpl;
import com.ticket.sass.provider.util.*;
import com.ticket.sass.provider.util.util.ResponseUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.TypeToken;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;


/**
 * 管理员业务
 * @author ywb
 * @date 2021-11-25 18:16
 */
@Slf4j
@Service
@AllArgsConstructor
public class AdminBusinessImpl implements AdminBusiness {
    
    final JwtUtil jwtUtil;
    final ModelUtil modelUtil;
//    final RedisCacheUtil redisCache;

    final AdminServiceImpl adminService;
    final CinemaServiceImpl cinemaService;
    final TenantCinemaMapServiceImpl tenantCinemaMapsService;

    @Override
    public void add(AdminAddInput input){
        if (adminService.count(new QueryWrapper<AdminEntity>().eq("username", input.getUsername())) > 0){
            throw new BadRequestException(
                ErrorCode.RECORD_EXIST,
                EscapeUtil.errorMessage("username", "该用户名已存在")
            );
        }


        AdminEntity admin = modelUtil.mapToMap(input, AdminEntity.class);
        admin.setPassword(new BCryptUtil(AppConfig.PWD_SECRET).encrypt(admin.getPassword()));
        admin.setTenantId(1l);
        
        adminService.save(admin);
    }

    @Override
    public PageModel<AdminListOutput> list(AdminListInput input) {
        IPage<AdminEntity> page = adminService.iPage(AdminEntity.class, input);
        List<AdminListOutput> outputs = modelUtil.listToList(
            page.getRecords(),
            new TypeToken<List<AdminListOutput>>(){}.getType()
        );

        return new PageModel<>(page.getTotal(), outputs);
    }

    @Override
    public void upd(AdminUpdInput input) {
        AdminEntity admin = adminService.getById(input.getId());
        if (Objects.isNull(admin)){
            throw new BadRequestException(
                ErrorCode.RECORD_NOT_EXIST,
                ErrorCode.RECORD_NOT_EXIST.getReasonPhrase()
            );
        }
        // 当 新账户名与旧账户名不相同 并且 查询新账户名在数据库中数量大于0时  即账户已经存在
        if (!input.getUsername().equals(admin.getUsername()) && adminService.count(new QueryWrapper<AdminEntity>().eq("username", input.getUsername())) > 0){
            throw new BadRequestException(
                ErrorCode.RECORD_EXIST,
                EscapeUtil.errorMessage("account", "该账户名已存在")
            );
        }

        admin = modelUtil.mapToMap(input, AdminEntity.class);
        String password = admin.getPassword();
        if (!StrUtil.isEmpty(password)){
            admin.setPassword(new BCryptUtil(AppConfig.PWD_SECRET).encrypt(password));
        }

        adminService.updateById(admin);

    }

    @Override
    public TokenModel login(AdminLoginInput input) {
        String ip = ResponseUtil.getRemoteHost(ResponseUtil.getRequest());
        String ipKey = String.format(AppConfig.VALID_LOGIN_COUNT_IP_KEY, ip);
    
//        int count = redisCache.getCacheObject(ipKey) == null ? 0 : redisCache.getCacheObject(ipKey);
//        if (count >= AppConfig.VALID_LOGIN_LIMIT){
//            throw new BadRequestException(
//                ErrorCode.FORBIDDEN,
//                "请求过于频繁，请稍后重试！"
//            );
//        }
        
        Long accountCount = adminService.count(new QueryWrapper<AdminEntity>().eq("username", input.getUsername()));
        if (accountCount > 1) {
            throw new BadRequestException(
                ErrorCode.SQL_DATA_ERROR,
                EscapeUtil.errorMessage("username", input.getUsername() + "存在" + accountCount + "个账户！")
            );
        }
        // 用户名 是 唯一的 根据用户名查询到用户
        AdminEntity admin = adminService.getOne(new QueryWrapper<AdminEntity>().eq("username", input.getUsername()));

        // 登录成功
        if (
            Objects.nonNull(admin) &&
            admin.getEnable() &&
            new BCryptUtil(AppConfig.PWD_SECRET).check(input.getPassword(), admin.getPassword())
        ){
//            redisCache.deleteObject(ipKey);
            
//            Integer tenantId = admin.getTenantId();
//            List<Integer> cinemaIds = tenantCinemaMapsService.getCinemaIdsByTenantId(tenantId);
            
            
//            AdminInfoOutput output = new AdminInfoOutput(admin.getId(), admin.getUsername(), admin.getEnable(), tenantId, cinemaService.getLabModels(new QueryWrapper<CinemaEntity>().in(cinemaIds.size() > 0, "id", cinemaIds)));
            
            // 成功存入redis 中 将权限一起保存
//            redisCache.setCacheObject(jwtUtil.validTokenCacheKey(admin.getId()), output.toJson(), 1, TimeUnit.DAYS);
        } else {
            throw new BadRequestException(
                ErrorCode.LOGIN_PARAMS_ERROR,
                ErrorCode.LOGIN_PARAMS_ERROR.getReasonPhrase()
            );
        }
        return jwtUtil.createToken(admin.getId(), admin.getUsername());
    }
    
    @Override
    public AdminInfoOutput info() {
        Long id = jwtUtil.getAudBy(ResponseUtil.getRequest());
        AdminEntity admin = adminService.getById(id);
        
//        String cacheObject = redisCache.getCacheObject(jwtUtil.validTokenCacheKey(id));
//        return GsonUtil.getInstance().fromJson(cacheObject, AdminInfoOutput.class);
        
        Long tenantId = admin.getTenantId();
        List<Long> cinemaIds = tenantCinemaMapsService.getCinemaIdsByTenantId(tenantId);
    
    
        AdminInfoOutput output = new AdminInfoOutput(admin.getId(), admin.getUsername(), admin.getEnable(), tenantId, cinemaService.getLabModels(new QueryWrapper<CinemaEntity>().in(cinemaIds.size() > 0, "id", cinemaIds)));
        return output;
    }

//    @Override
//    public AdminListOutput info() {
//        AdminEntity admin = adminService.getById(JwtUtil.adminIdByRequest(ResponseUtil.getRequest()));
//        AdminListOutput output = modelUtil.mapToMap(admin, AdminListOutput.class);
//        output.setRoleList(roleService.listByAdminId(output.getId()));
//        return output;
//    }
//
//    @Override
//    public void savePower(AdminPowerSaveInput input) {
//
//        CompareUtil<Integer> compare = new CompareUtil<>(adminResourceMapService.resourceIdByAdminId(input.getAdminId()), input.getResourceIds());
//
//        adminResourceMapService.removeByResourceId(compare.getDel());
//        List<AdminResourceMapEntity> addArray = compare.getInsert().stream().map(i ->  new AdminResourceMapEntity(input.getAdminId(), i)).collect(Collectors.toList());
//        adminResourceMapService.saveBatch(addArray);
//    }
//
//    @Override
//    public void logout() {
//        Integer adminId = JwtUtil.adminIdByRequest(ResponseUtil.getRequest());
//        redisCache.deleteObject(JwtUtil.validTokenCacheKey(adminId));
//    }
//
//    @Override
//    public List<RoleResourceOutput> resourceInfo() {
//        Integer adminId = JwtUtil.adminIdByRequest(ResponseUtil.getRequest());
//        List<ResourceEntity> list = resourceService.listByAdminId(adminId);
//        return DataUtil.menuFilterTool(list, 0);
//    }
//
//    @Override
//    public AdminResourceInfoOutPut info(Integer id) {
//        AdminEntity admin = adminService.getById(id);
//        if (Objects.isNull(admin)){
//            throw new BadRequestException(
//                ErrorCode.RECORD_NOT_EXIST,
//                ErrorCode.RECORD_NOT_EXIST.getReasonPhrase()
//            );
//        }
//
//        List<Integer> resourceIds = adminResourceMapService.resourceIdByAdminId(id);
//        List<Integer> roles = adminRoleMapService.roleIdsByAdminId(id);
//        List<Integer> roleResourceIds = roleResourceMapService.resourceIdByRoles(roles);
//
//        return new AdminResourceInfoOutPut(id, admin.getUsername(), resourceIds, roleResourceIds);
//    }
}
